
// 服务和特征UUID
#define SERVICE_UUID_STR "0000ffe0-0000-1000-8000-00805f9b34fb"
#define CHARACTERISTIC_UUID_STR "0000ffe1-0000-1000-8000-00805f9b34fb"
// 指定的蓝牙设备地址和名称
// const char *const TARGET_ADDRESS = "c8:47:80:01:89:92";
const char *const TARGET_DEVICE_NAME1 = "ESP32";
const char *const TARGET_DEVICE_NAME2 = "D30LE_018992";

// 连接状态标志
bool isConnected = false;
// 数据完整性状态标志
bool fullConnected = false;
// 客户端、设备及特征指针
BLEClient *pClient = nullptr;
BLEAdvertisedDevice *pServer = nullptr;
BLERemoteCharacteristic *pRemoteCharacteristic = nullptr;

// 超时时间（单位：毫秒）
unsigned long TIMEOUT_VALUE = 2000;
// 记录开始接收数据的时间
unsigned long receiveStartTime = 0;

// 搜索到设备时的回调类
class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks
{
  void onResult(BLEAdvertisedDevice advertisedDevice) override
  {
    if (advertisedDevice.getName() == TARGET_DEVICE_NAME1 || advertisedDevice.getName() == TARGET_DEVICE_NAME2)
    {
      // 停止扫描
      advertisedDevice.getScan()->stop();
      // 暂存设备
      pServer = new BLEAdvertisedDevice(advertisedDevice);
      sendtoData("发现设备");
      sendtoData(advertisedDevice.getName().c_str());
      sendtoData(advertisedDevice.getAddress().toString().c_str());
    }
  }
};

// 客户端连接与断开的回调类
class MyClientCallback : public BLEClientCallbacks
{
  void onConnect(BLEClient *pclient) override {}
  void onDisconnect(BLEClient *pclient) override
  {
    isConnected = false;
    fullConnected = false;
    sendtoData("蓝牙已断开");
  }
};

// 将uint8数组转换为十六进制字符串
bool uint8_array_to_hex_string(const uint8_t *array, int length, char *output)
{
  if (output == nullptr)
  {
    sendtoData("输出缓冲区指针为空");
    return false;
  }
  for (int i = 0; i < length; i++)
  {
    if (snprintf(output + (i * 2), 3, "%02X", array[i]) < 0)
    {
      sendtoData("转换十六进制字符串时出错");
      return false;
    }
  }
  return true;
}

float splitString(int a, int b, String input)
{

  String sub = input.substring(a, a + b);
  uint32_t value = strtoul(sub.c_str(), NULL, 16);
  if (b == 8)
  {
    // 将 32 位整数拆分为位
    uint8_t byte0 = (value >> 0) & 0xFF;
    uint8_t byte1 = (value >> 8) & 0xFF;
    uint8_t byte2 = (value >> 16) & 0xFF;
    uint8_t byte3 = (value >> 24) & 0xFF;

    // 按照 IEEE 754 标准进行解码
    union
    {
      float f;
      uint32_t u;
    } conv;

    conv.u = ((uint32_t)byte3 << 24) | ((uint32_t)byte2 << 16) | ((uint32_t)byte1 << 8) | byte0;

    return conv.f;
  }

  return value;
}

// 向BLE服务器发送数据
void sendtoBLEServer()
{
  static int a = 0;
  std::string hexData = "";
  if (pRemoteCharacteristic != nullptr && pRemoteCharacteristic->canWrite())
  {
    if (a == 0)
    {
      a++;
      hexData = "c50100bc614e"; //  第一页读取代码
    }
    else
    {
      a = 0;
      hexData = "5b0200bc614e"; // 第二页读取代码
    }
    // 将十六进制字符串转换为字节数组
    std::vector<uint8_t> bytes;
    for (size_t i = 0; i < hexData.length(); i += 2)
    {
      std::string byteString = hexData.substr(i, 2);
      char *endPtr;
      uint8_t byte = static_cast<uint8_t>(strtoul(byteString.c_str(), &endPtr, 16));
      if (*endPtr != '\0')
      {
        sendtoData("十六进制字符串转换为字节时出错");
        return;
      }
      bytes.push_back(byte);
    }
    // 发送数据
    pRemoteCharacteristic->writeValue(bytes.data(), bytes.size());
  }
}
// 收到服务推送的数据时的回调函数
void NotifyCallback(BLERemoteCharacteristic *pBLERemoteCharacteristic, uint8_t *pData, size_t length, bool isNotify)
{
  char hex_string[length * 2 + 1];                      // uint8_t *pData 转为十六进制字符串//length数据长度
  uint8_array_to_hex_string(pData, length, hex_string); // uint8_t * 转为十六进制字符串
  int substr = splitString(0, 2, hex_string);
  // for (size_t i = 0; i < length; i++)
  // {
  //   Serial.print(hex_string[i]);
  // }
  // Serial.print("strlen(hex_string):");
  // Serial.println(strlen(hex_string));
  if (substr == 1 && strlen(hex_string) == 80)
  {
    batteryPackVoltage = splitString(8, 8, hex_string);
    float out_I = splitString(16, 8, hex_string);
    float in_I = splitString(24, 8, hex_string);
    batteryPackCurrent = in_I - out_I;
    float Temp_1 = splitString(32, 8, hex_string);
    float Temp_2 = splitString(40, 8, hex_string);
    batteryPackTemperature = Temp_1 > Temp_2 ? Temp_1 : Temp_2;
    batteryPackCharge = splitString(76, 4, hex_string);
  }
  else if (substr == 2 && strlen(hex_string) == 96)
  {
    singleCellVoltages.clear();
    singleCellVoltages.push_back(splitString(48, 8, hex_string));
    singleCellVoltages.push_back(splitString(56, 8, hex_string));
    singleCellVoltages.push_back(splitString(64, 8, hex_string));
    singleCellVoltages.push_back(splitString(72, 8, hex_string));

    // 单体电池最小电压
    minCellVoltage = *std::min_element(singleCellVoltages.begin(), singleCellVoltages.end());
    // 单体电池最大电压
    maxCellVoltage = *std::max_element(singleCellVoltages.begin(), singleCellVoltages.end());
    // 电压差值
    voltageDifference = maxCellVoltage * 1000 - minCellVoltage * 1000;
  }
}

// 连接设备并获取服务与特征
bool ConnectToServer()
{
  pClient = BLEDevice::createClient();
  if (pClient == nullptr)
  {
    sendtoData("创建客户端失败");
    return false;
  }
  pClient->setClientCallbacks(new MyClientCallback());

  if (pServer == nullptr)
  {
    sendtoData("未找到目标设备");
    return false;
  }
  sendtoData("已找到目标设备");

  if (!pClient->connect(pServer))
  {
    sendtoData("连接设备失败");
    return false;
  }
  sendtoData("连接设备成功");

  BLERemoteService *pRemoteService = pClient->getService(SERVICE_UUID_STR);
  if (pRemoteService == nullptr)
  {
    sendtoData("获取服务失败");
    pClient->disconnect();
    return false;
  }
  sendtoData("获取服务成功");

  pRemoteCharacteristic = pRemoteService->getCharacteristic(CHARACTERISTIC_UUID_STR);
  if (pRemoteCharacteristic == nullptr)
  {
    sendtoData("获取特性失败");
    pClient->disconnect();
    return false;
  }
  sendtoData("获取特征成功");

  // if (pRemoteCharacteristic->canRead())
  // {
  //   Serial.printf("该特征值可以读取并且当前值为: ");
  //   std::string value = pRemoteCharacteristic->readValue();
  //   for (char c : value)
  //   {
  //     Serial.printf("%02X ", (unsigned char)c);
  //   }
  //   Serial.println();
  // }
  if (pRemoteCharacteristic->canNotify())
  {
    pRemoteCharacteristic->registerForNotify(NotifyCallback);
  }
  return true;
}

// 初始化蓝牙扫描
void setupBle()
{
  BLEDevice::init("");
  BLEScan *pBLEScan = BLEDevice::getScan();
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
  pBLEScan->setActiveScan(true);
  pBLEScan->setInterval(100);
  pBLEScan->setWindow(80);
}
// 启动蓝牙相关操作
void loopBle()
{
  if (millis() - receiveStartTime > TIMEOUT_VALUE)
  {
    if (!isConnected || !config.BleOnOff)
    {
      TIMEOUT_VALUE = 60000;
      if (!config.BleOnOff)
      {
        if (isConnected)
        {
          sendtoData("断开蓄电池......");
          pClient->disconnect();
          isConnected = false;
        }
      }
      else
      {
        sendtoData("搜索蓄电池......");
        BLEDevice::getScan()->clearResults();
        BLEDevice::getScan()->start(3, false); // 扫描5秒
        if (pServer != nullptr)
        {
          if (ConnectToServer())
          {
            isConnected = true;
            TIMEOUT_VALUE = 2000;
          }
        }
      }
    }
    else
    {
      sendtoBLEServer();
    }
    receiveStartTime = millis();
  }
}